package com.motu.monstercity.server.game.logic;

import com.motu.monstercity.module.common.iap.IapGift;
import com.motu.monstercity.module.common.network.ResponseUtils;
import com.motu.monstercity.module.common.servermanager.ServerInfo;
import com.motu.monstercity.module.common.servermanager.ServerManager;
import com.motu.monstercity.protocol.CmdEnum;
import com.motu.monstercity.protocol.Common.PBUserData;
import com.motu.monstercity.protocol.CsGameSystem;
import com.motu.monstercity.server.game.base.CommonUtils;
import com.motu.monstercity.server.game.base.ProtoDataUtils;
import com.motu.monstercity.server.game.commondata.act.Act;
import com.motu.monstercity.server.game.commondata.act.ActConstant;
import com.motu.monstercity.server.game.commondata.act.ActConvention;
import com.motu.monstercity.server.game.commondata.act.ActConventionTask;
import com.motu.monstercity.server.game.commondata.mail.MailConstant;
import com.motu.monstercity.server.game.commondata.rank.RankConstant;
import com.motu.monstercity.server.game.commondata.rank.RankReward;
import com.motu.monstercity.server.game.commondata.shop.Shop;
import com.motu.monstercity.server.game.commondata.shop.ShopConstant;
import com.motu.monstercity.server.game.commondata.system.SystemConstant;
import com.motu.monstercity.server.game.log.LogType;
import com.motu.monstercity.server.game.userdata.*;
import com.motu.monstercity.server.game.verticle.MainVerticle;
import com.motu.vertx.module.utility.model.BaseModel;
import com.motu.vertx.module.utility.redis.RedisTools;
import com.motu.vertx.module.utility.toolset.TimeUtils;
import com.motu.vertx.module.utility.toolset.Tool;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

public class ActConventionManager extends ActConventionUserData {

    /**
     * 是否可在商店购买道具
     * 1. 整个活动期
     * @param userInfo
     * @param subShopType
     * @return
     */
    public static boolean isShopBuyItem(UserInfo userInfo, int subShopType){
        Act act = ActManager.getActByType(ActConstant.ACT_TYPE_1001, userInfo.getServerId());
        if (act == null || !act.isCloseTime()) {// 整个活动期
            return false;
        }
        int groupId = Integer.parseInt(act.getParam());
        ActConvention actConvention = ActConventionManager.getActConvention(groupId);
        if (actConvention == null || subShopType != actConvention.getBoxShop()) { // 不是本期的可购买的道具类型
            return false;
        }

        return true;
    }

    /**
     * 是否可在商店购买宝箱
     * 1. 活动期间
     * @param userInfo
     * @param subShopType
     * @return
     */
    public static boolean isShopBuyBox(UserInfo userInfo, int subShopType){
        Act act = ActManager.getActByType(ActConstant.ACT_TYPE_1001, userInfo.getServerId());
        if (act == null || !act.isStart()) {// 活动期间
            return false;
        }

        int groupId = Integer.parseInt(act.getParam());
        ActConvention actConvention = ActConventionManager.getActConvention(groupId);
        if (actConvention == null) {
            return false;
        }
        if (subShopType != actConvention.getBoxShop() && subShopType != actConvention.getShop()) {
            return false;// 不是本期可以购买的宝箱，或是兑换的物品
        }
        return true;
    }

    /**
     * 是否可购买礼包
     * @param userInfo
     * @param iapGiftId
     * @return
     */
    public static  boolean isBuyIapGift(UserInfo userInfo, int iapGiftId) {
        Act act = ActManager.getActByType(ActConstant.ACT_TYPE_1001, userInfo.getServerId());
        if (act == null || !act.isCloseTime()) { // 只能在活动区间购买
            return false;
        }

        int groupId = Integer.parseInt(act.getParam());
        ActConvention actConvention = ActConventionManager.getActConvention(groupId);
        if (actConvention == null) {
            return false;
        }

        JsonArray giftArray = CommonUtils.strToJsonArray(actConvention.getIap());
        if (!Tool.isInList(giftArray, iapGiftId)) {
            return false;
        }

        return true;
    }

    /**
     * 是否可打开宝箱
     * @param userInfo
     * @param boxId
     * @return
     */
    public static  boolean isOpenBox(UserInfo userInfo, int boxId) {
        Act act = ActManager.getActByType(ActConstant.ACT_TYPE_1001, userInfo.getServerId());
        if (act == null || !act.isCloseTime()) { // 只能在活动区间购买
            return false;
        }

        int groupId = Integer.parseInt(act.getParam());
        ActConvention actConvention = ActConventionManager.getActConvention(groupId);
        if (actConvention == null) {
            return false;
        }

        JsonArray boxArray = CommonUtils.strToJsonArray(actConvention.getBox());
        if (!Tool.isInList(boxArray, boxId)) {
            return false;
        }

        return true;
    }

//    /**
//     * 登录重置活动
//     * @param userInfo
//     */
//    public static void loginResetActConvention(UserInfo userInfo) {
//        recycleItemConvertReward(userInfo);
//        resetActConvention(userInfo);
//    }
//
//    /**
//     * 重置活动道具
//     * @param userInfo
//     */
//    public static void resetActConvention(UserInfo userInfo) {
//        long userId = userInfo.getId();
//        Act act = ActManager.getActByType(ActConstant.ACT_TYPE_1001, userInfo.getServerId());
//        if (act != null) {
//            // 重置活动数据
//            boolean isReset = false;
//            UserActConvention userActConvention = getUserActConvention(userId);
//            if (userActConvention.getActId() == 0) {
//                isReset = true;// 第一次开启活动
//            } else if (userActConvention.getActId() > 0 && userActConvention.getActId() != act.getId()) {
//                isReset = true;// 开启新一期的活动
//            }
//            if (isReset) {
//                userActConvention.putActId(act.getId());
//                userActConvention.putScore(0);
//                userActConvention.putGroupId(Integer.parseInt(act.getParam()));
//                userActConvention.update();
//            }
//
//        }
//    }

    /**
     * 结算排行榜奖励
     * @param act
     */
    public  static void closeActConventionRankReward(Act act) {
        // 发放单服排名奖励
        MainVerticle.logger.info("close actId start:" + act.getId());
        ConcurrentHashMap<Integer, ServerInfo> serverList= ServerManager.getServerList();
        int rankType = RankConstant.ACTIVITY_RANK_CONVENTION;
        long actId = act.getId();
        int groupId = Integer.parseInt(act.getParam());
        for (ServerInfo server : serverList.values()) {
            if (!server.isMerged() && act.isContainServer(server.getServerId())) {// 该服有开启万能活动
                int rankMaxNum = RankManager.getRankTypeMaxNum(rankType);
                JsonArray serverRankList = RankManager.getRankIdListByIndex(rankType, server.getServerId(), String.valueOf(act.getId()), 0,  rankMaxNum - 1);
                MainVerticle.logger.info("## send  conventionRankReward reward actid = " + act.getId() + " rank size = " + serverRankList.size());
                for (int i = 0; i < serverRankList.size(); i++) {
                    int rank = i + 1;
                    long userId = Long.parseLong(serverRankList.getString(i));
                    RankReward rankReward = RankManager.getRankReward(rankType, rank, groupId);
                    if (rankReward != null) {
                        MainVerticle.logger.info("## send  conventionRankReward reward rankType " + rankType + " actid = " + actId + " rank = " + rank + " userId = " + userId);
                        String rankStr = rank + "";
                        MailManager.sendSystemMailReplaceContent(userId, MailConstant.RANK_ACT_CONVENTION_TITLE, MailConstant.RANK_ACT_CONVENTION_CONTENT, CommonUtils.takeReawrdItemFromStr(rankReward.getReward()), LogType.RANK_ACT_CONVENTION_REWARD, rankStr);
                    }
                }

                if (serverRankList.size() > 0) {
                    String rankKey = RankManager.getRankName(rankType, server.getServerId(), (int)act.getId());
                    RedisTools.expire(rankKey, 2 * TimeUtils.WEEK);
                }
            }
        }

        // 发放跨服排名奖励
        JsonArray serverGroupIdList = ServerManager.getWarZoneIdList();// 所有的战区分组
        int crossRankType = RankConstant.ACTIVITY_CROSS_RANK_CONVENTION;
        for (int gs = 0; gs < serverGroupIdList.size(); gs++) {
            int serverGroupId = serverGroupIdList.getInteger(gs);
            int crossRankMaxNum = RankManager.getRankTypeMaxNum(rankType);
            JsonArray crossServerRankList = RankManager.getRankIdListByIndex(crossRankType, serverGroupId, String.valueOf(act.getId()), 0,  crossRankMaxNum - 1);
            MainVerticle.logger.info("## send  conventionCrossRankReward reward actid = " + act.getId() + " rank size = " + crossServerRankList.size());
            for (int i = 0; i < crossServerRankList.size(); i++) {
                int crossRank = i + 1;
                long userId = Long.parseLong(crossServerRankList.getString(i));
                RankReward rankReward = RankManager.getRankReward(crossRankType, crossRank, groupId);
                if (rankReward != null) {
                    MainVerticle.logger.info("## send  conventionRankReward reward rankType " + crossRankType + " actid = " + actId + " rank = " + crossRank + " userId = " + userId);
                    String crossRankStr = crossRank + "";
                    MailManager.sendSystemMailReplaceContent(userId, MailConstant.RANK_CROSS_ACT_CONVENTION_TITLE, MailConstant.RANK_CROSS_ACT_CONVENTION_CONTENT, CommonUtils.takeReawrdItemFromStr(rankReward.getReward()), LogType.RANK_ACT_CONVENTION_REWARD, crossRankStr);
                }
            }

            if (crossServerRankList.size() > 0) {
                String rankKey = RankManager.getRankName(crossRankType, serverGroupId, act.getId());
                RedisTools.expire(rankKey, 2 * TimeUtils.WEEK);
            }
        }
    }


    /**
     * 回收道具转换成奖励
     * 活动结束后，发放给玩家
     * @param userInfo
     */
    public static void recycleItemConvertReward(UserInfo userInfo, UserActConvention userActConvention, Act act) {
        long userId = userInfo.getId();
        if (userActConvention.getGroupId() == 0) { // 已经回收过了
            return;
        }
        // 活动不存在 | 活动已结束 | 不是本期活动（活动连着开）
        if (act == null || act.getEndTime() < TimeUtils.getCurTime() || userActConvention.getActId() != act.getId()) {
            int groupId = userActConvention.getGroupId();
            ActConvention actConvention = ActConventionManager.getActConvention(groupId);
            if (actConvention == null) {
                return;
            }

            JsonArray jsonArray = CommonUtils.strToJsonArray(actConvention.getBox());
            List<RewardItem> recycleList = CommonUtils.takeReawrdItemFromStr(actConvention.getRecycle());
            if (jsonArray.isEmpty() || recycleList.isEmpty() || recycleList.size() != jsonArray.size()) {
                return;
            }

            List<RewardItem> rewardList = new ArrayList<>();
            PBUserData.Builder pbUserData = PBUserData.newBuilder();
            for (int i = 0; i < jsonArray.size(); i++) {
                int boxId = jsonArray.getInteger(i);
                long userItemNum = BagManager.getUserItemNum(userInfo, boxId);
                if (userItemNum > 0) {
                    RewardItem rewardItem = recycleList.get(i);
                    rewardItem.setItemNum(rewardItem.getItemNum() * userItemNum);
                    rewardList.add(rewardItem);
                    // 扣除道具
                    RewardManager.subReward(userInfo, boxId, userItemNum, pbUserData, LogType.ACT_CONVENTION_ITEM_RECYCLE_REISSUE_REWARD);
                }
            }

            if (!rewardList.isEmpty()) {
                MailManager.sendSystemMail(userId, MailConstant.ACT_ITEM_RECYCLE_REISSUE_TITLE, MailConstant.ACT_ITEM_RECYCLE_REISSUE_CONTENT, rewardList, LogType.ACT_CONVENTION_ITEM_RECYCLE_REISSUE_REWARD);
            }

            // 标记已回收，防止重复执行
            userActConvention.putGroupId(0);
            userActConvention.update();
        }
    }

    /******************** 任务模块 **********************/

    /**
     * 通用、主线任务更新
     * @param pbUserData
     * @param userInfo
     * @param taskType
     * @param num
     * @param param
     * @param isAdd
     */
    public static void updateTask(PBUserData.Builder pbUserData, UserInfo userInfo, int taskType, long num, int param, boolean isAdd) {
        if (num <= 0) {
            return;
        }
        long userId = userInfo.getId();
        Act act = ActManager.getActByType(ActConstant.ACT_TYPE_1001, userInfo.getServerId());
        if (act == null || !act.isCloseTime()) {
            return;
        }
        int groupId = Integer.parseInt(act.getParam());
        List<ActConventionTask> taskList = getActConventionTasksByGroupIdAndType(groupId, taskType);
        if (taskList == null || taskList.isEmpty()) {
            return;
        }
        UserActConventionTask userActConventionTask = updateTask(pbUserData, userId, taskType, num, param, isAdd);
        if (userActConventionTask != null) { // 红点通知
            for (ActConventionTask actConventionTask : taskList) {
                if (userActConventionTask.getCurP() < actConventionTask.getNum1()) {
                    continue;
                }

                JsonArray getRewardArray = userActConventionTask.getGetRewardArray();
                if (!getRewardArray.contains(actConventionTask.getId())) {
                    sendConventionTaskRedPrompt(userId);
                }
            }
        }

    }


    /**
     * 多级任务更新
     * @param pbUserData
     * @param userInfo
     * @param taskType
     * @param modelList
     * @param function
     * @param <T>
     */
    public static <T extends BaseModel> void updateOuterTask(PBUserData.Builder pbUserData, UserInfo userInfo, int taskType, List<T> modelList, DayTaskInterface<T> function) {
        long userId = userInfo.getId();
        Act act = ActManager.getActByType(ActConstant.ACT_TYPE_1001, userInfo.getServerId());
        if (act == null || !act.isCloseTime()) {
            return;
        }

        int groupId = Integer.parseInt(act.getParam());
        List<ActConventionTask> taskList = getActConventionTasksByGroupIdAndType(groupId, taskType);
        if (taskList == null || taskList.isEmpty()) {
            return;
        }
        if (taskList == null || taskList.isEmpty()) {
            return;
        }

        boolean isSend = false;
        for (ActConventionTask actConventionTask : taskList) {
            int param = actConventionTask.getNum2();
            int num = function.apply(modelList, param);
            UserActConventionTask userActConventionTask = updateTask(pbUserData, userId, taskType, num, param, false);
            if (userActConventionTask != null && !isSend) {
                if (userActConventionTask.getCurP() < actConventionTask.getNum1()) {
                    continue;
                }

                JsonArray getRewardArray = userActConventionTask.getGetRewardArray();
                if (!getRewardArray.contains(actConventionTask.getId())) {
                    sendConventionTaskRedPrompt(userId);
                    isSend = true;
                }
            }
        }
    }

    /**
     * 任务更新
     * @param pbUserData
     * @param userId
     * @param taskType
     * @param value
     * @param param
     * @param isAdd
     */
    private static UserActConventionTask updateTask(PBUserData.Builder pbUserData, long userId, int taskType, long value, int param, boolean isAdd) {
        int taskId = getTaskId(taskType, param);
        UserActConventionTask userActConventionTask = getUserActConventionTask(userId, taskId);
        if (userActConventionTask == null) {
            userActConventionTask = new UserActConventionTask(userId, taskId);
            userActConventionTask.doCreate();
        }
        boolean update = false;
        if (isAdd) {
            userActConventionTask.addCurP(value);
            update = true;
        } else {
            if (value > userActConventionTask.getCurP()) {
                userActConventionTask.putCurP(value);
                update = true;
            }
        }
        if (update) {
            userActConventionTask.update();
            ProtoDataUtils.updatePBUserData(pbUserData, userActConventionTask); // TODO 在联调是在看看 是否需要
            return userActConventionTask;
        }

        return null;
    }



    // 推送红点提示
    private static void sendConventionTaskRedPrompt(long userId) {
        CsGameSystem.CSGameSystemRedPointResponse.Builder builder = CsGameSystem.CSGameSystemRedPointResponse.newBuilder();
        builder.setPromptType(SystemConstant.RED_POINT_ACTIVITY_EVENT);
        CsGameSystem.RedPoint_ActConvention.Builder redBuild = CsGameSystem.RedPoint_ActConvention.newBuilder();
        redBuild.setTaskReward(true);
        builder.getActBuilder().setConvention(redBuild.build());
        JsonObject jsonObject = ResponseUtils.getRedpointResponseData(builder.build().toByteArray());
        GameUser.pushToUser(userId, jsonObject);
    }

    /**
     * 初始化任务
     * @param userInfo
     * @param groupId
     */
    public  static void initTask(UserInfo userInfo, int groupId) {
        long userId = userInfo.getId();
        List<UserActConventionTask> userActConventionTaskList = getUserActConventionTaskList(userId);
        Map<Integer, UserActConventionTask> userActConventionTaskMap = userActConventionTaskList.stream().collect(Collectors.toMap(UserActConventionTask::getTaskType, t -> t));
        List<ActConventionTask> actConventionTaskList = getActConventionTasksByGroupId(groupId);
        for (ActConventionTask actConventionTask : actConventionTaskList) {
            int taskTypeId = getTaskId(actConventionTask.getTaskType(), actConventionTask.getNum2());
            if (userActConventionTaskMap.containsKey(taskTypeId)) { // 已存在
                continue;
            }
            UserActConventionTask userActConventionTask = new UserActConventionTask(userId, taskTypeId);
            userActConventionTask.doCreate();
            userActConventionTaskMap.put(taskTypeId, userActConventionTask);
        }
    }

    /**
     * 红点检测
     * @param userInfo
     * @param res_build
     * @return
     */
    public static boolean checkRedPoint(UserInfo userInfo, CsGameSystem.CSGameSystemRedPointResponse.Builder res_build) {
        boolean hasRedPoint = false;
        long userId = userInfo.getId();
        Act act = ActManager.getActByType(ActConstant.ACT_TYPE_1001, userInfo.getServerId());
        if (act == null || !act.isCloseTime()) {
            return hasRedPoint;
        }
        int groupId = Integer.parseInt(act.getParam());
        ActConvention actConvention = ActConventionManager.getActConvention(groupId);
        if (actConvention == null) {
            return hasRedPoint;
        }

        CsGameSystem.RedPoint_ActConvention.Builder redBuild = CsGameSystem.RedPoint_ActConvention.newBuilder();
        JsonArray giftArray = CommonUtils.strToJsonArray(actConvention.getIap());
        // 是否有免费礼包
        for (int i = 0; i < giftArray.size(); i++) {
            int iapGiftId = giftArray.getInteger(i);
            IapGift iapGift = IapManager.getIapGift(iapGiftId);
            if (iapGift == null) {
                continue;
            }
            if (iapGift.getIapId() == 0) {
                UserIapGift userIapGift = IapManager.getUserIapGift(userId, iapGiftId);
                if (userIapGift == null || userIapGift.getNum() < iapGift.getLimitNum()) {
                    redBuild.setFreeGift(true);
                    hasRedPoint = true;
                    break;
                }
            }
        }


        initTask(userInfo, groupId);
        // 是否有任务奖励可领取
        List<ActConventionTask> actConventionTaskList = getActConventionTasksByGroupId(groupId);
        if (actConventionTaskList != null) {
            for (ActConventionTask actConventionTask : actConventionTaskList) {
                int taskId = getTaskId(actConventionTask.getTaskType(), actConventionTask.getNum2());
                UserActConventionTask userActConventionTask = getUserActConventionTask(userId, taskId);
                if (userActConventionTask == null || userActConventionTask.getCurP() < actConventionTask.getNum1()) {
                    continue;
                }

                JsonArray gainTaskArray = userActConventionTask.getGetRewardArray();
                if (!gainTaskArray.contains(actConventionTask.getId())) {
                    redBuild.setTaskReward(true);
                    hasRedPoint = true;
                    break;
                }
            }
        }

        // 是否有免费道具可以购买，配置在shop表
        UserShopLimit userShopLimit = ShopManager.getUserShopLimit(userId, ShopConstant.SHOP_TYPE_301);
        for (Shop shop : ShopManager.getShopMap().values()) {
            if (shop.getShopType() == ShopConstant.SHOP_TYPE_301 && shop.getIsFree() == 1 && shop.getSubShopType() == actConvention.getBoxShop() && ShopManager.checkShopLimit(userShopLimit, shop, 1)) {
                redBuild.setFreeShopBuy(true);
                hasRedPoint = true;
                break;
            }
        }


        if (hasRedPoint) {
            res_build.getActBuilder().setConvention(redBuild.build());
        }

        return hasRedPoint;
    }

}
